﻿using Dto;
using Furion.EventBus;
using Logics;
using Nito.AsyncEx;

namespace Events;

/// <summary>
/// 排队免单
/// </summary>
public class PointsActivity : IEventSubscriber, ISingleton
{
    private readonly ISqlSugarClient db;
    private readonly Common com;
    private readonly MoneyLogics money;
    private readonly AsyncLock locker = new AsyncLock();

    /// <summary>
    /// 排队免单
    /// </summary>
    /// <param name="db"></param>
    /// <param name="com"></param>
    /// <param name="money"></param>
    public PointsActivity(ISqlSugarClient db, Common com, MoneyLogics money)
    {
        this.db = db;
        this.com = com;
        this.money = money;
    }

    /// <summary>
    /// 加入排队队列
    /// </summary>
    /// <param name="ctx"></param>
    /// <returns></returns>
    [EventSubscribe("OrderComplete")]
    public async Task Join(Furion.EventBus.EventHandlerContext ctx)
    {
        var data = (Dto.OrderComplete)ctx.Source.Payload;

        var order = await com.GetOrder(data.OrderNo);

        if (order.OrderType != Entity.OrderType.排队免单) return;

        using (await locker.LockAsync())
        {
            var orderExt = await db.Queryable<Entity.Orders.Order_Out_PintsActivity>().FirstAsync(x => x.OrderNo == data.OrderNo);

            //目前排队的序号
            var active = await db.Queryable<Entity.PointsActivety.PointsActivity>().FirstAsync(x => x.Id == orderExt.ActiveId);

            int lastIndex = await db.Queryable<Entity.PointsActivety.PointsActivityQueue>().Where(x => x.ActiveId == orderExt.ActiveId).Select(x => SqlFunc.AggregateMax(x.Index)).FirstAsync();

            var queue = new Entity.PointsActivety.PointsActivityQueue
            {
                ClientId = order.UserId,

                StoreId = order.StoreId,

                ActiveId = orderExt.ActiveId,

                Index = lastIndex + 1,

                Price = order.PayPrice,

                ActivePrice = orderExt.ActivePrice,

                StorePrice = 0,

                RealPrice = orderExt.UserPrice
            };

            await db.Insertable(queue).ExecuteCommandAsync();

            await db.Updateable(active).ExecuteCommandHasChangeAsync();

            await SetActivePrice(order, orderExt, active);

            await money.Store(new ChangeMoneyAndLog
            {
                moneyType = Entity.MoneyType.排队收益,

                OrderId = order.Id,

                Price = order.PayPrice,

                Type = 1,

                Uid = order.StoreId
            });
        }
    }

    /// <summary>
    /// 设置排队活动的奖池信息
    /// </summary>
    /// <param name="order"></param>
    /// <param name="orderExt"></param>
    /// <param name="active"></param>
    /// <returns></returns>
    private async Task SetActivePrice(Entity.Order order, Entity.Orders.Order_Out_PintsActivity orderExt, Entity.PointsActivety.PointsActivity active)
    {

        #region 1.更新奖池信息

        //更新活动池金额
        active.CurrentPrice += orderExt.ActivePrice;

        //更新活动池金额
        active.TotalPrice += orderExt.ActivePrice;

        //更新活动池
        await db.Updateable(active).ExecuteCommandHasChangeAsync();
        #endregion

        #region 2.更新可以领奖人信息

        //获取当前排队用户的信息
        var currentUser = await db.Queryable<Entity.PointsActivety.PointsActivityQueue>()
            .Includes(x => x.Client)
            .FirstAsync(x => x.ActiveId == active.Id && x.Index == active.Index);

        //奖池得金额满足条件
        if (currentUser != null && currentUser.State == Entity.PointsActivety.ActiveState.进行中 && active.CurrentPrice >= currentUser.RealPrice)
        {
            currentUser.State = Entity.PointsActivety.ActiveState.可领奖;

            await db.Updateable(currentUser).ExecuteCommandHasChangeAsync();
        }

        #endregion

    }
}

